package com.binance.mbxgateway.web.service.impl;

import java.math.BigDecimal;
import java.util.Date;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpStatusCodeException;

import com.binance.assetservice.api.IProductApi;
import com.binance.assetservice.vo.request.product.PriceConvertRequest;
import com.binance.assetservice.vo.response.product.PriceConvertResponse;
import com.binance.master.error.BusinessException;
import com.binance.master.utils.CopyBeanUtils;
import com.binance.mbxgateway.vo.PriceConvertVo;
import com.binance.mbxgateway.vo.request.AddProductRequest;
import com.binance.mbxgateway.vo.request.OrderTypeRequest;
import com.binance.mbxgateway.web.service.IMatchboxService;
import com.binance.mbxgateway.web.service.IProductService;

import lombok.extern.slf4j.Slf4j;

/**
 * @author wangxiao
 */
@Service
@Slf4j
public class ProductServiceImpl extends BaseServiceImpl implements IProductService {

    final public static long NINE_O_CLOCK = 60 * 60 * 1000 * 9;
    @Autowired
    private IMatchboxService matchboxService;
    @Autowired
    private IProductApi productApi;
    @Value("${matching.unit.type}")
    private String matchingType;

    @Override
    public void setNumAlgoOrdersFilter(String symbol, Integer numOrders) throws Exception {
        try {
            this.matchboxService.postNumAlgoOrdersFilter(numOrders, symbol, null);
        } catch (HttpStatusCodeException e) {
            String errJson = e.getResponseBodyAsString();
            log.error("setNumAlgoOrdersFilter is error:{},{}", errJson, e);
            throw new BusinessException(errJson);
        } catch (Exception e) {
            log.error("setNumAlgoOrdersFilter exception: {}", e);
            throw e;
        }
    }

    @Override
    public void setIceicebergLimit(String symbol, Integer limit) throws Exception {
        try {
            this.matchboxService.postIcebergPartsFilter(limit, symbol);
        } catch (HttpStatusCodeException e) {
            String errJson = e.getResponseBodyAsString();
            log.error("setIceicebergLimit is error:{},{}", errJson, e);
            throw new BusinessException(errJson);
        } catch (Exception e) {
            log.error("setIceicebergLimit exception: {}", e);
            throw e;
        }
    }

    @Override
    public void setProductOrderTypes(OrderTypeRequest orderTypes) throws Exception {
        try {
            this.matchboxService.putOrderTypes(orderTypes.getEnableIceberg(), orderTypes.getEnableMarket(),
                    orderTypes.getEnableStopLoss(), orderTypes.getEnableStopLossLimit(),
                    orderTypes.getEnableTakeProfit(), orderTypes.getEnableTakeProfitLimit(), orderTypes.getSymbol());
        } catch (HttpStatusCodeException e) {
            String errJson = e.getResponseBodyAsString();
            log.error("setProductOrderTypes is error:{},{}", errJson, e);
            throw new BusinessException(errJson);
        } catch (Exception e) {
            log.error("setProductOrderTypes exception: {}", e);
            throw e;
        }
    }

    @Override
    public void addProduct(AddProductRequest request) throws Exception {
        String symbolType = StringUtils.defaultIfBlank(request.getSymbolType(), "SPOT");
        BigDecimal minQty = request.getMinQty() == null ? new BigDecimal(0.00000001) : request.getMinQty();
        BigDecimal maxQty = request.getMaxQty() == null ? new BigDecimal(92141578) : request.getMaxQty();
        BigDecimal maxPrice = request.getMaxPrice() == null ? new BigDecimal(1000) : request.getMaxPrice();
        String commissionType = StringUtils.defaultIfBlank(request.getCommissionType(), "GAS_OR_RECV_OPTIONAL");
        String matchingUnitType = StringUtils.defaultIfBlank(request.getMatchingUnitType(), matchingType);
        String mathSystemType = StringUtils.defaultIfBlank(request.getMathSystemType(), "FULL_CUT");
        try {
            this.matchboxService.postSymbol(request.getBaseAsset(), commissionType, maxPrice, maxQty, minQty,
                    request.getQuoteAsset(), request.getSymbol(), symbolType, matchingUnitType, mathSystemType);
            log.info("创建产品:%s 成功", request.getSymbol());
        } catch (HttpStatusCodeException e) {
            String responseString = e.getResponseBodyAsString();
            log.error("创建产品:{}调用撮合失败，{},{}", request.getSymbol(), responseString, e);
            throw new BusinessException(responseString);
        } catch (Exception e) {
            log.error("创建产品:{}失败，{}", request.getSymbol(), e);
            throw e;
        }
    }

    @Override
    public void creatAsset(String asset, String decimalPlaces) throws Exception {
        try {
            this.matchboxService.postAsset(asset, decimalPlaces);
        } catch (HttpStatusCodeException e) {
            String errJson = e.getResponseBodyAsString();
            log.error("creatAsset is error:{},{}", errJson, e);
            throw new BusinessException(errJson);
        } catch (Exception e) {
            log.error("creatAsset exception: {}", e);
            throw e;
        }
        log.info("创建asset:%s 成功", asset);
    }

    @Override
    public PriceConvertVo internalConvert(String from, String to, BigDecimal amount, Date date) throws Exception {
        PriceConvertRequest body = new PriceConvertRequest();
        body.setAmount(amount);
        body.setDate(date);
        body.setFrom(from);
        body.setTo(to);
        try {
            PriceConvertResponse response =
                    this.getAPIRequestResponse(this.productApi.priceConvert(this.newAPIRequest(body)));
            return CopyBeanUtils.copy(response, PriceConvertVo.class);
        } catch (Exception e) {
            log.error("转换出现异常（{} to {}）:{}", from, to, e);
            throw e;
        }
    }
}
